/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.tagservice.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.MessageUtil;
import com.lightkits.common.TransactionValidate;
import com.lightkits.common.db.entity.BdTag;
import com.lightkits.common.db.entity.BdTagHistory;
import com.lightkits.common.db.entity.BdTagThing;
import com.lightkits.common.db.entity.BdTagThingHistory;
import com.lightkits.common.db.entity.FndContainerTypeBase;
import com.lightkits.common.db.entity.FndDocumentTypeBase;
import com.lightkits.common.db.entity.FndItemBase;
import com.lightkits.common.db.entity.FndLocationBase;
import com.lightkits.common.db.entity.FndOrganizationBase;
import com.lightkits.common.db.entity.FndPartyBase;
import com.lightkits.common.db.entity.FndResourceBase;
import com.lightkits.common.db.entity.FndWarehouse;
import com.lightkits.common.db.entity.FndWmArea;
import com.lightkits.common.db.entity.event.BdEvent;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.logging.Logger;
import com.lightkits.framework.common.logging.LoggerFactory;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.date.DateUtil;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.wms.database.dao.WmsWarehouseMapper;
import com.lightkits.wms.database.model.KVCodeModel;
import com.lightkits.wms.domain.commons.service.WmsCommonsService;
import com.lightkits.wms.domain.tagservice.CreateTagParamsService;
import com.lightkits.wms.domain.tagservice.UseTagParamsService;
import com.lightkits.wms.domain.tagservice.model.TagDTO;
import com.lightkits.wms.domain.tagservice.repo.BdTagHistoryService;
import com.lightkits.wms.domain.tagservice.repo.BdTagService;
import com.lightkits.wms.domain.tagservice.repo.BdTagThingHistoryService;
import com.lightkits.wms.domain.tagservice.repo.BdTagThingService;
import com.lightkits.wms.dto.tagservice.model.CancelTagDto;
import com.lightkits.wms.dto.tagservice.model.TagViewDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 条码创建.
 *
 * @author jing.wei@hand-china.com.
 * Created on 2019/5/21 18:36.
 */
@Service
public class UseTagParamsServiceImpl implements UseTagParamsService {
    private final WmsWarehouseMapper wmsWarehouseMapper;
    private final Logger logger = LoggerFactory.getLogger(CreateTagParamsServiceImpl.class);
    private final WmsCommonsService wmsCommonsService;
    private final BdTagService bdTagService;
    private final BdTagHistoryService bdTagHistoryService;
    private final BdTagThingService bdTagThingService;
    private final BdTagThingHistoryService bdTagThingHistoryService;

    @Autowired
    public UseTagParamsServiceImpl(final WmsWarehouseMapper wmsWarehouseMapper,
                                   final WmsCommonsService wmsCommonsService,
                                   final BdTagService bdTagService,
                                   final BdTagHistoryService bdTagHistoryService,
                                   final BdTagThingService bdTagThingService,
                                   final BdTagThingHistoryService bdTagThingHistoryService,
                                   final CreateTagParamsService createTagParamsService) {
        this.wmsWarehouseMapper = wmsWarehouseMapper;
        this.wmsCommonsService = wmsCommonsService;
        this.bdTagService = bdTagService;
        this.bdTagHistoryService = bdTagHistoryService;
        this.bdTagThingService = bdTagThingService;
        this.bdTagThingHistoryService = bdTagThingHistoryService;
        this.createTagParamsService = createTagParamsService;
    }

    private final CreateTagParamsService createTagParamsService;

    /**
     * 校验条码参数
     *
     * @param viewDTOs 条码参数
     * @return IResult
     **/
    private IResult checkParams(List<TagViewDto> viewDTOs) {
        try {
            for (TagViewDto viewDTO : viewDTOs) {
                //参数必输校验
                IntegrityValidator.begin()
                        .validate(viewDTO.getTagType(), "Tag Type")
                        .validate(viewDTO.getOwnerOrgId(), "Owner Organization Id")
                        .validate(viewDTO.getTagCode(), "Tag Code")
                        .validate(viewDTO.getTagThingType(), "Tag Thing Type");

                IResult result = IResult.fail(MessageUtil.getSysMessage("NO_OR_INVALID"));
                //校验组织下仓库参数的有效性
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getWarehouseId())) {
                    FndWarehouse warehouse = new FndWarehouse()
                            .selectById(viewDTO.getWarehouseId());
                    if (warehouse == null || !String.valueOf(warehouse.getOrganizationId())
                            .equals(viewDTO.getOwnerOrgId())) {
                        return result;
                    }
                }
                //校验组织下货位参数的有效性
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getWmAreaId())) {
                    FndWmArea wmArea = new FndWmArea().selectById(viewDTO.getWmAreaId());
                    if (wmArea == null || !String.valueOf(wmArea.getOrganizationId())
                            .equals(viewDTO.getOwnerOrgId())) {
                        return result;
                    }
                }
                //校验组织下单据类型参数的有效性
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getDocumentTypeId())) {
                    FndDocumentTypeBase documentTypeBase = new FndDocumentTypeBase()
                            .selectById(viewDTO.getDocumentTypeId());
                    if (documentTypeBase == null
                            || !String.valueOf(documentTypeBase.getOrganizationId())
                            .equals(viewDTO.getOwnerOrgId())) {
                        return result;
                    }
                }
                //条码类型参数校验
                List<KVCodeModel> models = wmsWarehouseMapper
                        .querySysCode("FND_TAG_TYPE", viewDTO.getTagType(), "");
                if (models == null) {
                    return result;
                }
                //实物类型参数校验
                models = wmsWarehouseMapper.querySysCode("FND_TAG_THING_TYPE",
                        viewDTO.getTagThingType(), "");
                if (models == null) {
                    return result;
                }
                //1U1S的类型的条码对应数量为1
                if (viewDTO.getTagType().equals("1U1S") && !viewDTO.getQuantity().equals("1")) {
                    return IResult.fail(MessageUtil.getSysMessage("THIS_TAG_TYPE_QTY_MUST_BE_ONE"));
                }
                //仓库货位校验
                IResult result1 = wmsCommonsService
                        .checkLocationParams(viewDTO.getWarehouseId(), viewDTO.getWmAreaId());
                if (!result1.isSuccessful()) {
                    return result1;
                }
                //参数数字的数据格式校验
                Pattern pattern = Pattern.compile("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])");
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getQuantity())
                        && !pattern.matcher(viewDTO.getQuantity()).matches()) {
                    throw new LightKitsBizException("The Quantity is invalid");
                }
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getCapacityQty())
                        && !pattern.matcher(viewDTO.getCapacityQty()).matches()) {
                    throw new LightKitsBizException("The Capacity Quantity is invalid");
                }
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getPrimaryQuantity())
                        && !pattern.matcher(viewDTO.getPrimaryQuantity()).matches()) {
                    throw new LightKitsBizException("The Primary Quantity is invalid");
                }
                //1U1S和1U1T类型下校验参数的必输性
                if (viewDTO.getTagType().equals("1U1S")
                        || viewDTO.getTagType().equals("1U1T")) {
                    try {
                        IntegrityValidator.begin().validate(viewDTO.getItemId(), "Item Id")
                                .validate(viewDTO.getUomCode(), "Uom")
                                .validate(viewDTO.getTagCode(), "Tag Code")
                                .validate(viewDTO.getQuantity(), "Quantity")
                                .validate(viewDTO.getEventId(), "Event Id");
                        if (!viewDTO.getTagThingType().equals("ITEM")) {
                            return IResult.fail("the Tag Type is invalid");
                        }

                    } catch (LightKitsBizException e) {
                        return e.result();
                    }
                }
                //tagThingType为TAG时必输参数校验innerTagId
                if (viewDTO.getTagThingType().equals("TAG")) {
                    try {
                        IntegrityValidator.begin().validate(viewDTO.getInnerTagId(),
                                "Inner Tag Id");
                    } catch (LightKitsBizException e) {
                        return e.result();
                    }
                }
                //容器所有者类型和所有者参数的校验
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getContainerOwnerType())) {
                    result = wmsCommonsService.checkOwnerParams(viewDTO.getContainerOwnerType(),
                            viewDTO.getContainerOwnerId());
                    if (!result.isSuccessful()) {
                        return result;
                    }
                }
                //所有者类型和所有者参数的校验
                if (!ObjectUtil.isNullOrEmpty(viewDTO.getOwnerType())) {
                    result = wmsCommonsService.checkOwnerParams(viewDTO.getOwnerType(),
                            viewDTO.getOwnerId());
                    return result;
                }
            }

        } catch (LightKitsBizException e) {
            return e.result();
        }

        return IResult.success();
    }

    /**
     * 条码参数转换
     *
     * @param dtos 条码参数
     * @return TagDTO
     **/
    private List<TagDTO> convertDto(List<TagViewDto> dtos) {
        List<TagDTO> tags = new ArrayList<>();
        try {

            dtos.forEach(dto -> {
                TagDTO tag = new TagDTO();
                tag.setTagType(dto.getTagType());
                tag.setOwnerOrgId(ParseUtil.tryLongWithException(dto.getOwnerOrgId()));

                tag.setTagCode(dto.getTagCode());
                tag.setTagStatus(dto.getTagStatus());
                tag.setVerificationCode(dto.getVerificationCode());
                tag.setDCode(dto.getDCode());
                tag.setEventId(dto.getEventId());
                tag.setEventBy(dto.getEventBy());
                try {
                    tag.setEventTime(DateUtil.toDate(dto.getEventTime(), DateUtil.DEFAULT_DATETIME_PATTERN));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                tag.setProductCode(dto.getProductCode());
                tag.setStorageUnitCode(dto.getStorageUnitCode());
                tag.setContainerType(dto.getContainerType());
                tag.setContainerOwnerType(dto.getContainerOwnerType());
                tag.setRemark(dto.getRemark());
                tag.setTagThingType(dto.getTagThingType());
                tag.setUomCode(dto.getUomCode());
                tag.setPrimaryUomCode(dto.getPrimaryUomCode());
                if (!ObjectUtil.isNullOrEmpty(dto.getLotNumber())) {
                    tag.setLotNumber(dto.getLotNumber());
                }
                tag.setOwnerType(dto.getOwnerType());
                tag.setQcRemark(dto.getQcRemark());
                tag.setQcStatus(dto.getQcStatus());
                tag.setThingRemark(dto.getThingRemark());
                BdTag bdTag = new BdTag()
                        .selectOne(new EntityWrapper()
                                .eq(BdTag.TAG_CODE, dto.getTagCode()));
                if (bdTag != null) {
                    tag.setTagId(bdTag.getId());
                }
                //根据条件查询tagThing（实物条码）
                EntityWrapper<BdTagThing> entityWrapper = new EntityWrapper<>();
                if (!ObjectUtil.isNullOrEmpty(dto.getLotNumber())) {
                    entityWrapper.eq(BdTagThing.LOT_NUMBER, dto.getLotNumber());
                } else {
                    entityWrapper.isNull(BdTagThing.LOT_NUMBER);
                }
                if (!ObjectUtil.isEmpty(dto.getItemId())) {
                    entityWrapper.eq(BdTagThing.ITEM_ID, dto.getItemId());
                } else {
                    entityWrapper.isNull(BdTagThing.ITEM_ID);
                }
                if (!ObjectUtil.isEmpty(dto.getTagId())) {
                    entityWrapper.eq(BdTagThing.TAG_ID, dto.getTagId());
                } else {
                    entityWrapper.isNull(BdTagThing.TAG_ID);
                }
                BdTagThing tagThing = new BdTagThing().selectOne(entityWrapper);
                if (tagThing != null) {
                    tag.setTagThingId(tagThing.getId());
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getCapacityQty())) {
                    tag.setCapacityQty(new BigDecimal(dto.getCapacityQty()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getContainerId())) {
                    tag.setContainerId(ParseUtil.tryLongWithException(dto.getContainerId()));
                }

                if (!ObjectUtil.isNullOrEmpty(dto.getQuantity())) {
                    tag.setQuantity(new BigDecimal(dto.getQuantity()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getPrimaryQuantity())) {
                    tag.setPrimaryQuantity(new BigDecimal(dto.getPrimaryQuantity()));
                }


                if (!ObjectUtil.isNullOrEmpty(dto.getOuterTagId())) {
                    tag.setOuterTagId(ParseUtil.tryLongWithException(dto.getOuterTagId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getTagId())) {
                    tag.setTagId(ParseUtil.tryLongWithException(dto.getTagId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getResourceId())) {
                    tag.setResourceId(ParseUtil.tryLongWithException(dto.getResourceId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getLocationId())) {
                    tag.setLocationId(ParseUtil.tryLongWithException(dto.getLocationId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getWarehouseId())) {
                    tag.setWarehouseId(ParseUtil.tryLongWithException(dto.getWarehouseId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getWmAreaId())) {
                    tag.setWmAreaId(ParseUtil.tryLongWithException(dto.getWmAreaId()));
                }

                if (!ObjectUtil.isNullOrEmpty(dto.getDocumentTypeId())) {
                    tag.setDocumentTypeId(ParseUtil.tryLongWithException(dto.getDocumentTypeId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getDocumentId())) {
                    tag.setDocumentId(ParseUtil.tryLongWithException(dto.getDocumentId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getContainerOwnerId())) {
                    tag.setContainerOwnerId(ParseUtil.tryLongWithException(dto.getContainerOwnerId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getInnerTagId())) {
                    tag.setInnerTagId(ParseUtil.tryLongWithException(dto.getInnerTagId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getItemId())) {
                    tag.setItemId(ParseUtil.tryLongWithException(dto.getItemId()));
                }
                if (!ObjectUtil.isNullOrEmpty(dto.getOwnerId())) {
                    tag.setOwnerId(ParseUtil.tryLongWithException(dto.getOwnerId()));
                }
                tags.add(tag);
            });


        } catch (LightKitsBizException e) {
            logger.error("Convert Tag Dto.error", e);
            throw new LightKitsBizException(e);
        }
        return tags;
    }

    /**
     * 条码创建
     *
     * @param viewDTOs 条码参数
     * @return IResult
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult insertValue(List<TagViewDto> viewDTOs) {
            //条码参数校验
            IResult result = this.checkParams(viewDTOs);
            if (!result.isSuccessful()) {
                return result;
            }
            //条澳门参数转换
            List<TagDTO> dtos = this.convertDto(viewDTOs);
            //创建bd_tag条码
            List<BdTag> bdTags = createTagParamsService.createBdTag(dtos);


            Boolean tagFlag = bdTagService.insertOrUpdateBatch(bdTags);
            if (!tagFlag) {
                throw new LightKitsBizException("the Insert BdTag Failed!");
            }
            //创建条码历史纪录
           CheckResult checkResult = createTagParamsService.createBdTagHistory(dtos, bdTags);
            if (!checkResult.isSuccessful() || checkResult.getData() == null) {
                throw new LightKitsBizException(checkResult.getMessage());
            }
            List<BdTagHistory> bdTagHistory = (List<BdTagHistory>) checkResult.getData();
            if (!ObjectUtil.isNullOrEmpty(bdTagHistory)) {
                Boolean tagHistoryFlag = bdTagHistoryService.insertBatch(bdTagHistory);
                if (!tagHistoryFlag) {
                    throw new LightKitsBizException("the Insert BdTag History Failed!");
                }
            }


            //创建或修改实物条码
            checkResult = createTagParamsService.createBdTagThing(dtos, bdTags);
            if (!checkResult.isSuccessful() || checkResult.getData() == null) {
                throw new LightKitsBizException(checkResult.getMessage());
            }
            List<BdTagThing> bdTagThing = (List<BdTagThing>) checkResult.getData();
            if (!ObjectUtil.isNullOrEmpty(bdTagThing)) {
                Boolean tagThingFlag = bdTagThingService.insertOrUpdateBatch(bdTagThing);
                if (!tagThingFlag) {
                    throw new LightKitsBizException("the Insert BdTag Thing Failed!");
                }
            }

            checkResult = createTagParamsService.createBdTagThingHistory(dtos, bdTagThing, bdTags);
            if (!checkResult.isSuccessful() || checkResult.getData() == null) {
                throw new LightKitsBizException(checkResult.getMessage());
            }
            List<BdTagThingHistory> bdTagThingHistoryHistory =
                    (List<BdTagThingHistory>) checkResult.getData();
            if (!ObjectUtil.isNullOrEmpty(bdTagThingHistoryHistory)) {

                Boolean tagThingHistoryFlag =
                        bdTagThingHistoryService.insertBatch(bdTagThingHistoryHistory);
                if (!tagThingHistoryFlag) {
                    throw new LightKitsBizException("the Insert BdTag Thing History Failed!");
                }
            }
        return IResult.success();
    }

    /**
     * @param cancelTagDtos 取消条码参数
     * @return IResult
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult cancelTag(List<CancelTagDto> cancelTagDtos) {
            List<BdTag> tags = new ArrayList<>();
            cancelTagDtos.forEach(dto -> {
                if (ObjectUtil.isNullOrEmpty(dto.getTagCode())
                        && ObjectUtil.isNullOrEmpty(dto.getTagId())) {
                    throw new LightKitsBizException("the tagId Or TagCode All Empty");
                }
                if (ObjectUtil.isEmpty(dto.getEventId())) {
                    throw new LightKitsBizException("the Event Id is null");
                }
                TransactionValidate check = TransactionValidate
                        .beginValidity(BdEvent.class);
                check.checkIdValidity(
                        ObjectUtil.toString(dto.getEventId()), "ID");
                check = TransactionValidate
                        .beginValidity(BdTag.class);
                check.checkIdValidity(
                        ObjectUtil.toString(dto.getTagId()), "ID");
                check = TransactionValidate
                        .beginValidity(BdTag.class);
                check.checkIdValidity(
                        ObjectUtil.toString(dto.getTagCode()), "TAG_CODE");
                BdTag tag;
                if (!ObjectUtil.isNullOrEmpty(dto.getTagId())) {
                    tag = new BdTag().selectById(dto.getTagId());
                } else {
                    tag = new BdTag().selectOne(new EntityWrapper().eq(BdTag.TAG_CODE, dto.getTagCode()));
                }
                if (tag.getTagStatus().equals("SCRAPPED") || tag.getTagStatus().equals("END")) {
                    throw new LightKitsBizException(MessageUtil.getSysMessage("CODE_STATUS_ILLEGAL"));
                }
                if (!tag.getTagType().equals("1U1S") && !tag.getTagType().equals("1U1T")) {
                    throw new LightKitsBizException(MessageUtil.getSysMessage("CODE_TYPE_ILLEGAL"));
                }
                tag.setTagStatus("END");
                tags.add(tag);
            });


            Boolean cancelTagFlag = bdTagService.updateBatchById(tags);
            if (!cancelTagFlag) {
                throw new LightKitsBizException("the Cancel Tag Faild");
            }

            CheckResult checkResult = createTagParamsService.createCanBdTagHistory(tags, cancelTagDtos);
            if (!checkResult.isSuccessful() || checkResult.getData() == null) {
                throw new LightKitsBizException(checkResult.getMessage());
            }
            List<BdTagHistory> bdTagHistory = (List<BdTagHistory>) checkResult.getData();
            if (!ObjectUtil.isNullOrEmpty(bdTagHistory)) {
                Boolean tagHistoryFlag = bdTagHistoryService.insertBatch(bdTagHistory);
                if (!tagHistoryFlag) {
                    throw new LightKitsBizException("the Insert BdTag History Failed!");

                }
            }
        return IResult.success();
    }

}
